/************************************************************
   Copyright 2008 Abhinav Pobbati

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*************************************************************/

#include "HkPrerequisites.h"

#include "Havok4Xna/Common/Base/Math/HkTransform.h"
#include "Havok4Xna/Common/Base/Math/HkVector4.h"
#include "Havok4Xna/Common/Base/Math/HkMatrix3.h"
#include "Havok4Xna/Common/Base/Types/HkContactPoint.h"
#include "Havok4Xna/Physics/ConstraintSolver/HkpConstraintSolver.h"
#include "Havok4Xna/Physics/Dynamics/Constraint/HkpConstraint.h"
#include "Havok4Xna/Common/Base/Types/HkStepInfo.h"

namespace Havok4Xna {
	namespace Physics {
		namespace ConstraintSolver {

			HkpSolverInfo::DeactivationInfo::DeactivationInfo() {
				_setThis(new hkpSolverInfo::DeactivationInfo(), true);
			}
			IMPL_SIMPLE_PROPERTY_GETSET(float, LinearVelocityThresholdInv, m_linearVelocityThresholdInv, HkpSolverInfo::DeactivationInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, AngularVelocityThresholdInv, m_angularVelocityThresholdInv, HkpSolverInfo::DeactivationInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, SlowObjectVelocityMultiplier, m_slowObjectVelocityMultiplier, HkpSolverInfo::DeactivationInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, RelativeSteepVelocityThreshold, m_relativeSleepVelocityThreshold, HkpSolverInfo::DeactivationInfo);
			float HkpSolverInfo::DeactivationInfo::MaxDistSqrd0::get() {
				return _this()->m_maxDistSqrd[0];
			}
			void HkpSolverInfo::DeactivationInfo::MaxDistSqrd0::set(float v) {
				_this()->m_maxDistSqrd[0] = v;
			}
			float HkpSolverInfo::DeactivationInfo::MaxDistSqrd1::get() {
				return _this()->m_maxDistSqrd[1];
			}
			void HkpSolverInfo::DeactivationInfo::MaxDistSqrd1::set(float v) {
				_this()->m_maxDistSqrd[1] = v;
			}
			float HkpSolverInfo::DeactivationInfo::MaxRotSqrd0::get() {
				return _this()->m_maxRotSqrd[0];
			}
			void HkpSolverInfo::DeactivationInfo::MaxRotSqrd0::set(float v) {
				_this()->m_maxRotSqrd[0] = v;
			}
			float HkpSolverInfo::DeactivationInfo::MaxRotSqrd1::get() {
				return _this()->m_maxRotSqrd[1];
			}
			void HkpSolverInfo::DeactivationInfo::MaxRotSqrd1::set(float v) {
				_this()->m_maxRotSqrd[1] = v;
			}


			IMPL_SIMPLE_PROPERTY_GETSET(float, One, m_one, HkpSolverInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, Tau, m_tau, HkpSolverInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, Damping, m_damping, HkpSolverInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, FrictionTau, m_frictionTau, HkpSolverInfo);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSolverInfo, GlobalAccelerationPerSubStep, HkVector4,
				hkpSolverInfo, m_globalAccelerationPerSubStep, hkVector4);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSolverInfo, GlobalAccelerationPerStep, HkVector4,
				hkpSolverInfo, m_globalAccelerationPerStep, hkVector4);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSolverInfo, IntegrateVelocityFactor, HkVector4,
				hkpSolverInfo, m_integrateVelocityFactor, hkVector4);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSolverInfo, InvIntegrateVelocityFactor, HkVector4,
				hkpSolverInfo, m_invIntegrateVelocityFactor, hkVector4);
			IMPL_SIMPLE_PROPERTY_GETSET(float, DampDivTau, m_dampDivTau, HkpSolverInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, TauDivDamp, m_tauDivDamp, HkpSolverInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, DampDivFrictionTau, m_dampDivFrictionTau, HkpSolverInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, FrictionTauDivDamp, m_frictionTauDivDamp, HkpSolverInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, ContactRestingVelocity, m_contactRestingVelocity, HkpSolverInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, DeltaTime, m_deltaTime, HkpSolverInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, InvDeltaTime, m_invDeltaTime, HkpSolverInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(int, NumSteps, m_numSteps, HkpSolverInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(int, NumMicroSteps, m_numMicroSteps, HkpSolverInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, InvNumMicroSteps, m_invNumMicroSteps, HkpSolverInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, InvNumSteps, m_invNumSteps, HkpSolverInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(bool, ForceCoherentConstraintOrderingInSolver, m_forceCoherentConstraintOrderingInSolver,
				HkpSolverInfo);
			hkUint8 HkpSolverInfo::DeactivationNumInactiveFramesSelectFlag0::get() {
				return _this()->m_deactivationNumInactiveFramesSelectFlag[0];
			}
			void HkpSolverInfo::DeactivationNumInactiveFramesSelectFlag0::set(hkUint8 v) {
				_this()->m_deactivationNumInactiveFramesSelectFlag[0] = v;
			}
			hkUint8 HkpSolverInfo::DeactivationNumInactiveFramesSelectFlag1::get() {
				return _this()->m_deactivationNumInactiveFramesSelectFlag[1];
			}
			void HkpSolverInfo::DeactivationNumInactiveFramesSelectFlag1::set(hkUint8 v) {
				_this()->m_deactivationNumInactiveFramesSelectFlag[1] = v;
			}
			IMPL_SIMPLE_PROPERTY_GETSET(hkUint8, DeactivationIntegrateCounter, m_deactivationIntegrateCounter, HkpSolverInfo)

			HkpSolverInfo::HkpSolverInfo() {
				_setThis(new hkpSolverInfo(), true);
			}
			void HkpSolverInfo::SetTauAndDamping(float tau, float damping) {
				_this()->setTauAndDamping(tau, damping);
			}
			void HkpSolverInfo::IncrementDeactivationFlags() {
				_this()->incrementDeactivationFlags();
			}


			Hkp1dBilateralConstraintStatus::Hkp1dBilateralConstraintStatus() {
				_setThis(new hkp1dBilateralConstraintStatus(), true);
			}
			IMPL_SIMPLE_PROPERTY_GETSET(float, VirtualMass, m_virtualMass, Hkp1dBilateralConstraintStatus);


			Hkp1dConstraintMotorInfo::Hkp1dConstraintMotorInfo() {
				_setThis(new hkp1dConstraintMotorInfo(), true);
			}
			IMPL_SIMPLE_PROPERTY_GETSET(float, TargetPosition, m_targetPosition, Hkp1dConstraintMotorInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, TargetVelocity, m_targetVelocity, Hkp1dConstraintMotorInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, MaxForce, m_maxForce, Hkp1dConstraintMotorInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, MinForce, m_minForce, Hkp1dConstraintMotorInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, Tau, m_tau, Hkp1dConstraintMotorInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, Damping, m_damping, Hkp1dConstraintMotorInfo);
			IMPL_SIMPLE_PROPERTY_GETTER(int, IsModifierType, isModifierType, HkpConstraintAtom);
			HkpConstraintAtom::AtomType HkpConstraintAtom::Type::get() {
				return (HkpConstraintAtom::AtomType) _this()->getType();
			}


			Hkp2dAngConstraintAtom::Hkp2dAngConstraintAtom()
				: HkpConstraintAtom(new hkp2dAngConstraintAtom(), true) {
			}
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, FreeRotationAxis, m_freeRotationAxis, Hkp2dAngConstraintAtom);


			HkpAngConstraintAtom::HkpAngConstraintAtom()
				: HkpConstraintAtom(new hkpAngConstraintAtom(), true) {
			}
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, FirstConstrainedAxis, m_firstConstrainedAxis, HkpAngConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, NumConstrainedAxes, m_numConstrainedAxes, HkpAngConstraintAtom);


			HkpAngFrictionConstraintAtom::HkpAngFrictionConstraintAtom()
				: HkpConstraintAtom(new hkpAngFrictionConstraintAtom(), true) {
			}
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, IsEnabled, m_isEnabled, HkpAngFrictionConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, FirstFrictionAxis, m_firstFrictionAxis, HkpAngFrictionConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, NumFrictionAxes, m_numFrictionAxes, HkpAngFrictionConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, MaxFrictionTorque, m_maxFrictionTorque, HkpAngFrictionConstraintAtom);


			HkpAngLimitConstraintAtom::HkpAngLimitConstraintAtom()
				: HkpConstraintAtom(new hkpAngLimitConstraintAtom(), true) {
			}
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, IsEnabled, m_isEnabled, HkpAngLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, LimitAxis, m_limitAxis, HkpAngLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, MinAngle, m_minAngle, HkpAngLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, MaxAngle, m_maxAngle, HkpAngLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, AngularLimitsTauFactor, m_angularLimitsTauFactor, HkpAngLimitConstraintAtom);


			HkpAngMotorConstraintAtom::HkpAngMotorConstraintAtom()
				: HkpConstraintAtom(new hkpAngMotorConstraintAtom(), true) {
			}
			IMPL_SIMPLE_PROPERTY_GETSET(bool, IsEnabled, m_isEnabled, HkpAngMotorConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, MotorAxis, m_motorAxis, HkpAngMotorConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(System::Int16, InitializedOffset, m_initializedOffset, HkpAngMotorConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(System::Int16, PreviousTargetAngleOffset, m_previousTargetAngleOffset,
				HkpAngMotorConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(System::Int16, CorrespondingAngLimitSolverResultOffset, 
				m_correspondingAngLimitSolverResultOffset, HkpAngMotorConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, TargetAngle, m_targetAngle, HkpAngMotorConstraintAtom);


			HkpBallSocketConstraintAtom::HkpBallSocketConstraintAtom()
				: HkpConstraintAtom(new hkpBallSocketConstraintAtom(), true) {
			}
			HkpConstraintAtom ^HkpBallSocketConstraintAtom::Next() {
				hkpConstraintAtom *next = _ref().next();
				if(next == nullptr)
					return nullptr;
				return gcnew HkpConstraintAtom(next, false);
			}
			void HkpBallSocketConstraintAtom::AddToConstraintInfo([Out] HkpConstraintInfo ^infoOut) {
				// TODO:
			}
			IMPL_SIMPLE_PROPERTY_GETTER(int, NumSolverResults, numSolverResults, HkpBallSocketConstraintAtom);


			HkpBridgeConstraintAtom::HkpBridgeConstraintAtom()
				: HkpConstraintAtom(new hkpBridgeConstraintAtom(), true) {
			}
			void HkpBridgeConstraintAtom::Init(HkpConstraintData ^constraintData) {
				_ref().init(&constraintData->_ref());
			}
			HkpConstraintAtom ^HkpBridgeConstraintAtom::Next() {
				hkpConstraintAtom *next = _ref().next();
				if(next == nullptr)
					return nullptr;
				return gcnew HkpConstraintAtom(next, false);
			}
			IMPL_SIMPLE_PROPERTY_GETTER(int, NumSolverResults, numSolverResults, HkpBridgeConstraintAtom);
			IMPL_COMPLEX_PROPERTY_GETSET_2(
				HkpBridgeConstraintAtom, ConstraintData, HkpConstraintData,
				hkpBridgeConstraintAtom, m_constraintData, hkpConstraintData);



			HkpBridgeAtoms::HkpBridgeAtoms() {
				_setThis(new hkpBridgeAtoms(), true);
			}
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpBridgeAtoms, BridgeAtom, HkpBridgeConstraintAtom,
				hkpBridgeAtoms, m_bridgeAtom, hkpBridgeConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETTER(int, SizeOfAllAtoms, getSizeOfAllAtoms, HkpBridgeAtoms);


			HkpSimpleContactConstraintAtom::HkpSimpleContactConstraintAtom()
				: HkpConstraintAtom(new hkpSimpleContactConstraintAtom(), true) {
			}


			HkpConeLimitConstraintAtom::HkpConeLimitConstraintAtom()
				: HkpConstraintAtom(new hkpConeLimitConstraintAtom(), true) {
			}
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, IsEnabled, m_isEnabled, HkpConeLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, TwistAxisInA, m_twistAxisInA, HkpConeLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, RefAxisInB, m_refAxisInB, HkpConeLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, MemOffsetToAngleOffset, m_memOffsetToAngleOffset, HkpConeLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, MinAngle, m_minAngle, HkpConeLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, MaxAngle, m_maxAngle, HkpConeLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, AngularLimitsTauFactor, m_angularLimitsTauFactor, HkpConeLimitConstraintAtom);
			HkpConeLimitConstraintAtom::MeasurementMode HkpConeLimitConstraintAtom::AngleMeasurementMode::get() {
				return (HkpConeLimitConstraintAtom::MeasurementMode) ((hkUint8) _ref().m_angleMeasurementMode);
			}
			void HkpConeLimitConstraintAtom::AngleMeasurementMode::set(HkpConeLimitConstraintAtom::MeasurementMode v) {
				return _ref().m_angleMeasurementMode = (hkpConeLimitConstraintAtom::MeasurementMode) v;
			}


			HkpConstraintMotorInput::HkpConstraintMotorInput()
				: Hkp1dBilateralConstraintStatus(new hkpConstraintMotorInput(), true) {
			}
			IMPL_GENERIC_COMPLEX_PROPERTY_GET(
				HkpConstraintMotorInput, StepInfo, HkpConstraintQueryStepInfo, (hkpConstraintQueryStepInfo*) _ref().m_stepInfo.val());
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpConstraintMotorInput, LastResults, HkpSolverResults,
				hkpConstraintMotorInput, m_lastResults, hkpSolverResults);
			IMPL_SIMPLE_PROPERTY_GETSET(float, DeltaTarget, m_deltaTarget, HkpConstraintMotorInput);
			IMPL_SIMPLE_PROPERTY_GETSET(float, PositionError, m_positionError, HkpConstraintMotorInput);


			HkpConstraintQueryStepInfo::HkpConstraintQueryStepInfo() {
				_setThis(new hkpConstraintQueryStepInfo(), true);
			}
			IMPL_SIMPLE_PROPERTY_GETSET(float, SubstepInvDeltaTime, m_substepInvDeltaTime, HkpConstraintQueryStepInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, SubstepDeltaTime, m_substepDeltaTime, HkpConstraintQueryStepInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, MicroStepDeltaTime, m_microStepDeltaTime, HkpConstraintQueryStepInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, FrameDeltaTime, m_frameDeltaTime, HkpConstraintQueryStepInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, FrameInvDeltaTime, m_frameInvDeltaTime, HkpConstraintQueryStepInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, InvNumSteps, m_invNumSteps, HkpConstraintQueryStepInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, InvNumStepsTimesMicroSteps, m_invNumStepsTimesMicroSteps, HkpConstraintQueryStepInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, RhsFactor, m_rhsFactor, HkpConstraintQueryStepInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, VirtMassFactor, m_virtMassFactor, HkpConstraintQueryStepInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, FrictionRhsFactor, m_frictionRhsFactor, HkpConstraintQueryStepInfo);


			// HkSolverResults
			IMPL_SIMPLE_PROPERTY_GETTER(float, ImpulseApplied, getImpulseApplied, HkpSolverResults);


			HkpConstraintQueryIn::HkpConstraintQueryIn()
				: HkpConstraintQueryStepInfo(new hkpConstraintQueryIn(), true) {
			}
			IMPL_COMPLEX_PROPERTY_GETSET_2(
				HkpConstraintQueryIn, ConstraintInstance, HkpConstraintInstance,
				hkpConstraintQueryIn, m_constraintInstance, hkpConstraintInstance);
			HkpVelocityAccumulator ^HkpConstraintQueryIn::BodyA::get() {
				return _BodyA;
			}
			void HkpConstraintQueryIn::BodyA::set(HkpVelocityAccumulator ^v) {
				_ref().m_bodyA = v->_this();
				_BodyA = v;
			}
			HkpVelocityAccumulator ^HkpConstraintQueryIn::BodyB::get() {
				return _BodyB;
			}
			void HkpConstraintQueryIn::BodyB::set(HkpVelocityAccumulator ^v) {
				_ref().m_bodyB = v->_this();
				_BodyB = v;
			}
			HkTransform ^HkpConstraintQueryIn::TransformA::get() {
				return _TransformA;
			}
			void HkpConstraintQueryIn::TransformA::set(HkTransform ^v) {
				_ref().m_transformA = v->_this();
				_TransformA = v;
			}
			HkTransform ^HkpConstraintQueryIn::TransformB::get() {
				return _TransformB;
			}
			void HkpConstraintQueryIn::TransformB::set(HkTransform ^v) {
				_ref().m_transformB = v->_this();
				_TransformB = v;
			}
			IMPL_SIMPLE_PROPERTY_GETSET(float, Tau, m_tau, HkpConstraintQueryIn);
			IMPL_SIMPLE_PROPERTY_GETSET(float, Damping, m_damping, HkpConstraintQueryIn);
			IntPtr HkpConstraintQueryIn::ConstraintRuntime::get() {
				return IntPtr(_ref().m_constraintRuntime.val());
			}
			void HkpConstraintQueryIn::ConstraintRuntime::set(IntPtr ptr) {
				_ref().m_constraintRuntime = (void*) ptr;
			}
			IMPL_SIMPLE_PROPERTY_GETSET(hkUint32, AccumulatorAIndex, m_accumulatorAIndex, HkpConstraintQueryIn);
			IMPL_SIMPLE_PROPERTY_GETSET(hkUint32, AccumulatorBIndex, m_accumulatorBIndex, HkpConstraintQueryIn);
			void HkpConstraintQueryIn::Set(HkpSolverInfo ^si, HkStepInfo ^stepInfo) {
				_ref().set(si->_ref(), stepInfo->_ref());
			}


			HkpVelocityAccumulator::HkpVelocityAccumulator() {
				_setThis(new hkpVelocityAccumulator(), true);
			}
			void HkpVelocityAccumulator::SetFixed() {
				_ref().setFixed();
			}
			IMPL_SIMPLE_PROPERTY_GETSET(bool, MatrixIsIdentity, m_matrixIsIdentity, HkpVelocityAccumulator);
			IMPL_SIMPLE_PROPERTY_GETSET(hkUint32, DeactivationClass, m_deactivationClass, HkpVelocityAccumulator);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpVelocityAccumulator, LinearVel, HkVector4,
				hkpVelocityAccumulator, m_linearVel, hkVector4);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpVelocityAccumulator, AngularVel, HkVector4,
				hkpVelocityAccumulator, m_angularVel, hkVector4);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpVelocityAccumulator, InvMasses, HkVector4,
				hkpVelocityAccumulator, m_invMasses, hkVector4);
			IMPL_GENERIC_COMPLEX_PROPERTY_GETSET(
				HkpVelocityAccumulator, CenterOfMassInWorld, HkVector4,
				&_ref().getCenterOfMassInWorld(), _ref().getCenterOfMassInWorld(), _ref());
			IMPL_GENERIC_COMPLEX_PROPERTY_GETSET(
				HkpVelocityAccumulator, SumLinearVel, HkVector4,
				&_ref().getSumLinearVel(), _ref().getSumLinearVel(), _ref());
			IMPL_GENERIC_COMPLEX_PROPERTY_GETSET(
				HkpVelocityAccumulator, SumAngularVel, HkVector4,
				&_ref().getSumAngularVel(), _ref().getSumAngularVel(), _ref());
			IMPL_COMPLEX_PROPERTY_GETTER(
				HkpVelocityAccumulator, CoreFromWorldMatrix, HkRotation,
				hkpVelocityAccumulator, getCoreFromWorldMatrix, hkRotation);
			inline static void HkpVelocityAccumulator_CoreFromWorldMatrix_set(hkpVelocityAccumulator &velAcc, hkRotation &val) {
				velAcc.getCoreFromWorldMatrix() = val;
			}
			void HkpVelocityAccumulator::CoreFromWorldMatrix::set(HkRotation ^val) {
				HkpVelocityAccumulator_CoreFromWorldMatrix_set(_ref(), val->_ref());
			}


			HkpLinConstraintAtom::HkpLinConstraintAtom()
				: HkpConstraintAtom(new hkpLinConstraintAtom(), true) {
			}
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, AxisIndex, m_axisIndex, HkpLinConstraintAtom);


			HkpLinFrictionConstraintAtom::HkpLinFrictionConstraintAtom()
				: HkpConstraintAtom(new hkpLinFrictionConstraintAtom(), true) {
			}
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, IsEnabled, m_isEnabled, HkpLinFrictionConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, FrictionAxis, m_frictionAxis, HkpLinFrictionConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, MaxFrictionForce, m_maxFrictionForce, HkpLinFrictionConstraintAtom);


			HkpLinLimitConstraintAtom::HkpLinLimitConstraintAtom()
				: HkpConstraintAtom(new hkpLinLimitConstraintAtom(), true) {
			}
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, AxisIndex, m_axisIndex, HkpLinLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, Min, m_min, HkpLinLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, Max, m_max, HkpLinLimitConstraintAtom);


			HkpLinMotorConstraintAtom::HkpLinMotorConstraintAtom()
				: HkpConstraintAtom(new hkpLinMotorConstraintAtom(), true) {
			}
			IMPL_SIMPLE_PROPERTY_GETSET(bool, IsEnabled, m_isEnabled, HkpLinMotorConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, MotorAxis, m_motorAxis, HkpLinMotorConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(hkInt16, InitializedOffset, m_initializedOffset, HkpLinMotorConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(hkInt16, PreviousTargetPositionOffset, m_previousTargetPositionOffset,
				HkpLinMotorConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, TargetPosition, m_targetPosition, HkpLinMotorConstraintAtom);


			HkpLinSoftConstraintAtom::HkpLinSoftConstraintAtom()
				: HkpConstraintAtom(new hkpLinSoftConstraintAtom(), true) {
			}
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, AxisIndex, m_axisIndex, HkpLinSoftConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, Tau, m_tau, HkpLinSoftConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, Damping, m_damping, HkpLinSoftConstraintAtom);


			HkpPulleyConstraintAtom::HkpPulleyConstraintAtom()
				: HkpConstraintAtom(new hkpPulleyConstraintAtom(), true) {
			}
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpPulleyConstraintAtom, FixedPivotAinWorld, HkVector4,
				hkpPulleyConstraintAtom, m_fixedPivotAinWorld, hkVector4);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpPulleyConstraintAtom, FixedPivotBinWorld, HkVector4,
				hkpPulleyConstraintAtom, m_fixedPivotBinWorld, hkVector4);
			IMPL_SIMPLE_PROPERTY_GETSET(float, RopeLength, m_ropeLength, HkpPulleyConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, LeverageOnBodyB, m_leverageOnBodyB, HkpPulleyConstraintAtom);

			
			HkpRagdollMotorConstraintAtom::HkpRagdollMotorConstraintAtom()
				: HkpConstraintAtom(new hkpRagdollMotorConstraintAtom(), true) {
			}
			Havok4Xna::Physics::Dynamics::HkpConstraintMotor ^HkpRagdollMotorConstraintAtom::GetMotor(int motorNum) {
				return gcnew Havok4Xna::Physics::Dynamics::HkpConstraintMotor(_ref().m_motors[motorNum], false);
			}
			IMPL_SIMPLE_PROPERTY_GETSET(bool, IsEnabled, m_isEnabled, HkpRagdollMotorConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(hkInt16, InitializedOffset, m_initializedOffset, HkpRagdollMotorConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(hkInt16, PreviousTargetAnglesOffset, m_previousTargetAnglesOffset, HkpRagdollMotorConstraintAtom);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpRagdollMotorConstraintAtom, TargetFrameAinB, HkMatrix3,
				hkpRagdollMotorConstraintAtom, m_targetFrameAinB, hkMatrix3);


			HkpSetLocalRotationsConstraintAtom::HkpSetLocalRotationsConstraintAtom()
				: HkpConstraintAtom(new hkpSetLocalRotationsConstraintAtom(), true) {
			}
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSetLocalRotationsConstraintAtom, RotationA, HkRotation,
				hkpSetLocalRotationsConstraintAtom, m_rotationA, hkRotation);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSetLocalRotationsConstraintAtom, RotationB, HkRotation,
				hkpSetLocalRotationsConstraintAtom, m_rotationB, hkRotation);


			HkpSetLocalTransformsConstraintAtom::HkpSetLocalTransformsConstraintAtom()
				: HkpConstraintAtom(new hkpSetLocalTransformsConstraintAtom(), true) {
			}
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSetLocalTransformsConstraintAtom, TransformA, HkTransform,
				hkpSetLocalTransformsConstraintAtom, m_transformA, hkTransform);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSetLocalTransformsConstraintAtom, TransformB, HkTransform,
				hkpSetLocalTransformsConstraintAtom, m_transformB, hkTransform);


			HkpSetLocalTranslationsConstraintAtom::HkpSetLocalTranslationsConstraintAtom()
				: HkpConstraintAtom(new hkpSetLocalTranslationsConstraintAtom(), true) {
			}
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSetLocalTranslationsConstraintAtom, TranslationA, HkVector4,
				hkpSetLocalTranslationsConstraintAtom, m_translationA, hkVector4);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSetLocalTranslationsConstraintAtom, TranslationB, HkVector4,
				hkpSetLocalTranslationsConstraintAtom, m_translationB, hkVector4);


#pragma unmanaged
			inline static hkpSimpleConstraintInfo *HkpSimpleConstraintInfo_create() {
				return new hkpSimpleConstraintInfo();
			}
#pragma managed
			HkpSimpleConstraintInfo::HkpSimpleConstraintInfo() {
				_setThis(HkpSimpleConstraintInfo_create(), true);
			}
			IMPL_GENERIC_SIMPLE_PROPERTY_GETTERSETTER(
				float, Mass00, _ref().getMass00(),
				_ref().getMass00(), HkpSimpleConstraintInfo);
			IMPL_GENERIC_SIMPLE_PROPERTY_GETTERSETTER(
				float, InvDetM12, _ref().getInvDetM12(),
				_ref().getInvDetM12(), HkpSimpleConstraintInfo);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSimpleConstraintInfo, Base, HkRotation,
				hkpSimpleConstraintInfo, m_base, hkRotation);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSimpleConstraintInfo, InvMassMatrix, HkMatrix3,
				hkpSimpleConstraintInfo, m_invMassMatrix, hkMatrix3);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSimpleConstraintInfo, MassMatrix, HkMatrix3,
				hkpSimpleConstraintInfo, m_massMatrix, hkMatrix3);


			HkpSimplexSolverInput::HkpSimplexSolverInput() {
				_setThis(new hkpSimplexSolverInput(), true);
			}
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSimplexSolverInput, Position, HkVector4,
				hkpSimplexSolverInput, m_position, hkVector4);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSimplexSolverInput, Velocity, HkVector4,
				hkpSimplexSolverInput, m_velocity, hkVector4);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSimplexSolverInput, MaxSurfaceVelocity, HkVector4,
				hkpSimplexSolverInput, m_maxSurfaceVelocity, hkVector4);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSimplexSolverInput, UpVector, HkVector4,
				hkpSimplexSolverInput, m_upVector, hkVector4);
			IMPL_SIMPLE_PROPERTY_GETSET(float, DeltaTime, m_deltaTime, HkpSimplexSolverInput);
			IMPL_SIMPLE_PROPERTY_GETSET(float, MinDeltaTime, m_minDeltaTime, HkpSimplexSolverInput);
			IMPL_SIMPLE_PROPERTY_GETSET(int, NumConstraints, m_numConstraints, HkpSimplexSolverInput);


			HkpSimplexSolverOutput::HkpSimplexSolverOutput() {
				_setThis(new hkpSimplexSolverOutput(), true);
			}
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSimplexSolverOutput, Position, HkVector4,
				hkpSimplexSolverOutput, m_position, hkVector4);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSimplexSolverOutput, Velocity, HkVector4,
				hkpSimplexSolverOutput, m_velocity, hkVector4);
			IMPL_SIMPLE_PROPERTY_GETSET(float, DeltaTime, m_deltaTime, HkpSimplexSolverOutput);


			HkpStiffSpringConstraintAtom::HkpStiffSpringConstraintAtom()
				: HkpConstraintAtom(new hkpStiffSpringConstraintAtom(), true) {
			}
			IMPL_SIMPLE_PROPERTY_GETSET(float, Length, m_length, HkpStiffSpringConstraintAtom);


			HkpSurfaceConstraintInfo::HkpSurfaceConstraintInfo() {
				_setThis(new hkpSurfaceConstraintInfo(), true);
			}
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSurfaceConstraintInfo, Plane, HkVector4,
				hkpSurfaceConstraintInfo, m_plane, hkVector4);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpSurfaceConstraintInfo, Velocity, HkVector4,
				hkpSurfaceConstraintInfo, m_velocity, hkVector4);
			IMPL_SIMPLE_PROPERTY_GETSET(float, StaticFriction, m_staticFriction, HkpSurfaceConstraintInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, ExtraUpStaticFriction, m_extraUpStaticFriction, HkpSurfaceConstraintInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, ExtraDownStaticFriction, m_extraDownStaticFriction, HkpSurfaceConstraintInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(float, DynamicFriction, m_dynamicFriction, HkpSurfaceConstraintInfo);
			IMPL_SIMPLE_PROPERTY_GETSET(int, Priority, m_priority, HkpSurfaceConstraintInfo);


			HkpSurfaceConstraintInteraction::HkpSurfaceConstraintInteraction() {
				_setThis(new hkpSurfaceConstraintInteraction(), true);
			}
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, Touched, m_touched, HkpSurfaceConstraintInteraction);
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, Stopped, m_stopped, HkpSurfaceConstraintInteraction);
			IMPL_SIMPLE_PROPERTY_GETSET(float, SurfaceTime, m_surfaceTime, HkpSurfaceConstraintInteraction);


			HkpTwistLimitConstraintAtom::HkpTwistLimitConstraintAtom()
				: HkpConstraintAtom(new hkpTwistLimitConstraintAtom(), true) {
			}
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, IsEnabled, m_isEnabled, HkpTwistLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, TwistAxis, m_twistAxis, HkpTwistLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(System::Byte, RefAxis, m_refAxis, HkpTwistLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, MinAngle, m_minAngle, HkpTwistLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, MaxAngle, m_maxAngle, HkpTwistLimitConstraintAtom);
			IMPL_SIMPLE_PROPERTY_GETSET(float, AngularLimitsTauFactor, m_angularLimitsTauFactor, HkpTwistLimitConstraintAtom);


			HkpVehicleFrictionSolverAxleParams::HkpVehicleFrictionSolverAxleParams() {
				_setThis(new hkpVehicleFrictionSolverAxleParams(), true);
			}
			void HkpVehicleFrictionSolverAxleParams::Initialize() {
				_ref().initialize();
			}
			IMPL_SIMPLE_PROPERTY_GETSET(float, SlipVelocityFactor, m_slipVelocityFactor, HkpVehicleFrictionSolverAxleParams);


#pragma unmanaged
			inline static hkpVehicleFrictionSolverParams *HkpVehicleFrictionSolverParams_create() {
				return new hkpVehicleFrictionSolverParams();
			}
#pragma managed
			HkpVehicleFrictionSolverParams::HkpVehicleFrictionSolverParams() {
				_setThis(HkpVehicleFrictionSolverParams_create(), true);
			}
			/*HkpVehicleFrictionSolverAxleParams ^HkpVehicleFrictionSolverParams::GetAxleParam(int index) {
				return gcnew HkpVehicleFrictionSolverAxleParams(&_ref().m_axleParams[index], false);
			}
			void HkpVehicleFrictionSolverParams::SetAxleParam(int index, HkpVehicleFrictionSolverAxleParams ^param) {
				_ref().m_axleParams[index] = param->_ref();
			}*/
			IMPL_SIMPLE_PROPERTY_GETSET(float, MaxVelocityForPositionalFriction,
				m_maxVelocityForPositionalFriction, HkpVehicleFrictionSolverParams);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpVehicleFrictionSolverParams, Chassis, HkpVelocityAccumulator,
				hkpVehicleFrictionSolverParams, m_chassis, hkpVelocityAccumulator);
			IMPL_COMPLEX_PROPERTY_GETSET(
				HkpVehicleFrictionSolverParams, ChassisAtLastIntegration, HkpVelocityAccumulator,
				hkpVehicleFrictionSolverParams, m_chassisAtLastIntegration, hkpVelocityAccumulator);


			// Implement interface HkContactPointMaterial
			//IMPL_INTERFACE_HkContactPointMaterial(HkpContactPointProperties)

			/*float HkpContactPointProperties::HkContactPointMaterial::Friction::get() {
				return 0;
			}*/
		}
	}
}
